#include "stdafx.h"

#include "Player.h"
#include "SolidMap.h"
#include "Dialogue.h"
#include "GameObject.h"
#include "FreezingArea.h"

sf::SoundBuffer* Player::jumpBuffer = 0;
sf::Sound* Player::jumpSound = 0;

Player gMale;
Player gFemale;

sf::Texture gViewArea;
sf::Sprite gViewAreaSprite;
static int timer = 0;

const static sf::Vector2f PLAYER_SIZE(70.0f, 150.0f);
const static sf::Vector2f HPLAYER_SIZE = PLAYER_SIZE / 2.0f;

extern sf::View gView;

Player::Player(): pos(200, 0), vel(0, 0), mCanJump(false), mFreezingArea(0), animTimer(0.f)
{
	if (!jumpBuffer)
	{
		jumpBuffer = new sf::SoundBuffer();
		jumpBuffer->loadFromFile("data/sounds/jump.wav");
		jumpSound = new sf::Sound(*jumpBuffer);
	}
}

void Player::LoadAnims()
{
	if (IsFemale())
	{
		idleAnim = new Anim("data/female_idle.png", 1, 1.f);
		walkAnim = new Anim("data/female_walk.png", 8, .5f);
		jumpAnim = new Anim("data/female_jump.png", 1, 1.f);
		fallAnim = new Anim("data/female_jump_down.png", 1, 1.f);
		ladderAnim = new Anim("data/female_ladder_anim.png", 3, .25f);
	}
	else
	{
		idleAnim = new Anim("data/male_idle.png", 1, 100.0f);
		walkAnim = new Anim("data/male_walk.png", 8, .5f);
		jumpAnim = new Anim("data/male_jump.png", 1, 1.f);
		fallAnim = new Anim("data/male_jump_down.png", 1, 1.f);
		ladderAnim = new Anim("data/male_ladder_anim.png", 4, .25f);
	}
	activeAnim = idleAnim;
	gViewArea.loadFromFile("data/view_area.png");
	gViewAreaSprite.setTexture(gViewArea);
	sf::Vector2f size = sf::Vector2f(gViewArea.getSize().x, gViewArea.getSize().y);
	gViewAreaSprite.setOrigin(size/2.0f);
	gViewArea.setRepeated(true);
}


void Player::Step()
{
	timer+=4;

	if(mFreezingArea && mFreezingArea->active)
		return;

	activeAnim = 0;

	for(unsigned int i=0; i<gGameObjects.size(); i++)
	{
		GameObject* go = gGameObjects[i];
		if(go->CollideWithPlayer(this))
		{
			go->OnTouch(this);
		}
	}

	float force = 50.0f;
	float max_x_vel = 200.0f;
	float max_y_vel = 400.0f; 
	float gravity = 10.0f;
	float ladderSpeed = 200.0f;

	Player* other = this == &gFemale ? &gMale : &gFemale;

	bool doGravity = true;

	if(CollideWithLadder())
	{
		doGravity = false;
		bool moved = false;
		if(IsFemale())
		{
			if(sf::Keyboard::isKeyPressed(sf::Keyboard::Left) && other->pos.x < pos.x + gView.getSize().x )	{ vel.x -= force; moved = true; }
			if(sf::Keyboard::isKeyPressed(sf::Keyboard::Right) && other->pos.x > pos.x - gView.getSize().x) { vel.x += force; moved = true; }
			if(sf::Keyboard::isKeyPressed(sf::Keyboard::Up))	{ vel.y -= force; moved = true; }
			if(sf::Keyboard::isKeyPressed(sf::Keyboard::Down))	{ vel.y += force; moved = true; }
		} else
		{
			if(sf::Keyboard::isKeyPressed(sf::Keyboard::A) && other->pos.x < pos.x + gView.getSize().x)	{ vel.x -= force; moved = true; }
			if(sf::Keyboard::isKeyPressed(sf::Keyboard::D) && other->pos.x > pos.x - gView.getSize().x) { vel.x += force; moved = true; }
			if(sf::Keyboard::isKeyPressed(sf::Keyboard::W))	{ vel.y -= force; moved = true; }
			if(sf::Keyboard::isKeyPressed(sf::Keyboard::S))	{ vel.y += force; moved = true; }
		}
		activeAnim = ladderAnim;
		if(moved)
		{
			activeAnim->Step();
		}
	} else
	{
		if(IsFemale())
		{
			if(sf::Keyboard::isKeyPressed(sf::Keyboard::Left) && other->pos.x < pos.x + gView.getSize().x)
			{
				vel.x -= force;
				activeAnim = walkAnim;
				activeAnim->Step(true);
			}
			if(sf::Keyboard::isKeyPressed(sf::Keyboard::Right) && other->pos.x > pos.x - gView.getSize().x)
			{
				vel.x += force;
				activeAnim = walkAnim;
				activeAnim->Step();
			}
			if(sf::Keyboard::isKeyPressed(sf::Keyboard::Up))	Jump();
		} else
		{
			if(sf::Keyboard::isKeyPressed(sf::Keyboard::A) && other->pos.x < pos.x + gView.getSize().x)
			{
				vel.x -= force;
				activeAnim = walkAnim;
				activeAnim->Step(true);
			}
			if(sf::Keyboard::isKeyPressed(sf::Keyboard::D) && other->pos.x > pos.x - gView.getSize().x)
			{
				vel.x += force;
				activeAnim = walkAnim;
				activeAnim->Step();
			}
			if(sf::Keyboard::isKeyPressed(sf::Keyboard::W)) Jump();
		}
	}

	if(doGravity)
		vel.y += gravity;
	if(vel.y > max_y_vel) vel.y = max_y_vel;
	if(vel.y < -max_y_vel) vel.y = -max_y_vel;

	if(vel.y > 0) mCanJump = true;

	if(vel.x > max_x_vel) vel.x = max_x_vel;
	if(vel.x < -max_x_vel) vel.x = -max_x_vel;

	if(doGravity == false)
		mCanJump = false;

	bool lastValid = !CollideWithTiles();

	sf::Vector2f lastPos = pos;

	if(sf::Keyboard::isKeyPressed(sf::Keyboard::M) && this == &gFemale)
		vel.y = -400;
	if(sf::Keyboard::isKeyPressed(sf::Keyboard::N) && this == &gMale)
		vel.y = -400;

	pos.y += vel.y * DELTA;

	if(lastValid && CollideWithTiles())
	{
		pos.y = lastPos.y;
		vel.y = 0;
	}

	bool onHalf = false;

	if((IsFemale() && !sf::Keyboard::isKeyPressed(sf::Keyboard::Down)) || 
		(!IsFemale() && !sf::Keyboard::isKeyPressed(sf::Keyboard::S)))
	{

		int startY = lastPos.y+HPLAYER_SIZE.y;
		int stopY = pos.y+HPLAYER_SIZE.y;

		int startX = pos.x;
		int stopX = pos.x;

		for(int i=startY+1; startY < stopY && i<=stopY; i++)
		{
			for(int j=startX; j<=stopX; j++)
			{
				if(CollideWithHalfs(j, i) && !CollideWithHalfs(j, i-1))
				{
					pos.y = i - 1 - HPLAYER_SIZE.y;
					vel.y = 0;
				}
			}
		}

	}

	if (vel.y < -5.0f && doGravity)
	{
		activeAnim = jumpAnim;
		activeAnim->Step(vel.x < .0f);
	}
	else if (vel.y > 5.0f  && doGravity)
	{
		activeAnim = fallAnim;
		activeAnim->Step(vel.x < .0f);
	}
	pos.x += vel.x * DELTA;

	if(lastValid && CollideWithTiles())
	{
		pos.x = lastPos.x;
		vel.x = 0;
	}

	vel.x *= 0.8f;
	if(!doGravity)
		vel.y *= 0.9f;

	if (!activeAnim)
	{
		if(animTimer > 0.2f)
		{
			activeAnim = idleAnim;
			lastActiveAnim = idleAnim;
			animTimer = 0.f;
		}
		else
		{
			activeAnim = lastActiveAnim;
			animTimer += DELTA;
		}
	}
	else
		lastActiveAnim = activeAnim;
}

void Player::Draw(sf::RenderWindow& window)
{
	gViewAreaSprite.setPosition(pos);
	gViewAreaSprite.setTextureRect(sf::IntRect(timer, 0, gViewArea.getSize().x, gViewArea.getSize().y));
	if(!IsFemale())
	{
		gViewAreaSprite.setRotation(90.0f);
	} else
	{
		gViewAreaSprite.setRotation(0.0f);
	}

	unsigned char alpha = 255;

	if(CollideWithTiles())
		alpha = 128;

	activeAnim->Draw(window, pos, alpha);

	sf::RenderStates rs;
	rs.blendMode = sf::BlendMode::BlendAdd;

	window.draw(gViewAreaSprite, rs);
}

bool Player::CollideWithTiles()
{
	return gSolidMap.Vs(pos.x-HPLAYER_SIZE.x, pos.y-HPLAYER_SIZE.y, PLAYER_SIZE.x, PLAYER_SIZE.y);
}

bool Player::CollideWithHalfs(int x, int y)
{
	int destY = gMale.pos.y - HPLAYER_SIZE.y + 50;
	if(x >= gMale.pos.x - HPLAYER_SIZE.x && x <= gMale.pos.x + HPLAYER_SIZE.x && y == destY)
		return true;

	return gHalfSolidMap.IsSolid(x, y) || gMaleHalfSolidMap.IsSolid(x, y) || gFemaleHalfSolidMap.IsSolid(x, y);
}

bool Player::CollideWithLadder()
{
	if(IsFemale() == false && gOnlyMaleLaddersMap.Vs(pos.x-HPLAYER_SIZE.x, pos.y-HPLAYER_SIZE.y, PLAYER_SIZE.x, PLAYER_SIZE.y))
		return true;

	return gLaddersMap.Vs(pos.x-HPLAYER_SIZE.x, pos.y-HPLAYER_SIZE.y, PLAYER_SIZE.x, PLAYER_SIZE.y) 
		|| gMaleLaddersMap.Vs(pos.x-HPLAYER_SIZE.x, pos.y-HPLAYER_SIZE.y, PLAYER_SIZE.x, PLAYER_SIZE.y);
}

void Player::Jump()
{
	if(vel.y == 0 && mCanJump)
	{
		vel.y = -400;
		mCanJump = false;
		activeAnim = jumpAnim;
		activeAnim->Reset();
		jumpSound->play();
	}
}

void Player::Freeze(FreezingArea* area)
{
	if (area != mFreezingArea)
	{
		mFreezingArea = area;
		mFreezingArea->freezeSound->play();
		activeDialogue.Load(mFreezingArea->mDialogue1Texts, mFreezingArea->mDialogue1People);
	}
}

sf::Vector2f Player::GetSize()
{
	return PLAYER_SIZE;
}